#pragma once

#include <cstring>
#include <iostream>

// LIKELY / UNLIKELY：使用 GCC/Clang 的内建函数向编译器提示分支预测倾向。
// - LIKELY(x)  表示表达式 x 预期大概率为 true。
// - UNLIKELY(x) 表示表达式 x 预期大概率为 false。
// 这些提示可帮助编译器在生成机器码时优化热点路径的布局。
#define LIKELY(x)   __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)

/**
 * @brief 带消息的运行时断言。
 *
 * @param cond  要求成立的条件表达式。
 * @param msg   当条件失败时输出的错误信息。
 *
 * 行为说明：
 *  1. `UNLIKELY(!cond)`：告知编译器该分支发生概率低，从而提高正常路径的性能。
 *  2. 若断言失败，输出统一格式的错误消息到标准错误流。
 *  3. 使用 `exit(EXIT_FAILURE)` 立即终止进程，确保在严重错误时不会继续执行。
 *
 * @note 函数标记为 `noexcept`，承诺不会抛出异常；这样可在敏感场景（如析构函数或低层系统代码中）
 *       安全调用而无需担心异常传播。
 */
inline auto ASSERT(bool cond, const std::string& msg) noexcept {
  if (UNLIKELY(!cond)) {
    std::cerr << "ASSERT : " << msg << std::endl; // 输出断言失败的具体信息
    exit(EXIT_FAILURE);                            // 非正常退出程序
  }
}

/**
 * @brief 致命错误报告工具。
 *
 * @param msg 打印到标准错误流的错误信息。
 *
 * 行为说明：
 *  1. 无条件打印带前缀的错误描述。
 *  2. 立即调用 `exit(EXIT_FAILURE)` 终止程序，表示不可恢复的严重错误。
 *
 * @note 与 ASSERT 不同，FATAL 没有条件判断，适合用于逻辑上不允许继续执行的路径。
 */
inline auto FATAL(const std::string& msg) noexcept {
  std::cerr << "FATAL : " << msg << std::endl; // 输出致命错误信息
  exit(EXIT_FAILURE);                          // 非正常退出程序
}